%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file is part of the Prolog Development Tool (PDT)
% 
% Author: Lukas Degener (among others) 
% E-mail: degenerl@cs.uni-bonn.de
% WWW: http://roots.iai.uni-bonn.de/research/pdt 
% Copyright (C): 2004-2006, CS Dept. III, University of Bonn
% 
% All rights reserved. This program is  made available under the terms 
% of the Eclipse Public License v1.0 which accompanies this distribution, 
% and is available at http://www.eclipse.org/legal/epl-v10.html
% 
% In addition, you may at your option use, modify and redistribute any
% part of this program under the terms of the GNU Lesser General Public
% License (LGPL), version 2.1 or, at your option, any later version of the
% same license, as long as
% 
% 1) The program part in question does not depend, either directly or
%   indirectly, on parts of the Eclipse framework and
%   
% 2) the program part in question does not include files that contain or
%   are derived from third-party work and are therefor covered by special
%   license agreements.
%   
% You should have received a copy of the GNU Lesser General Public License
% along with this program; if not, write to the Free Software Foundation,
% Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
%   
% ad 1: A program part is said to "depend, either directly or indirectly,
%   on parts of the Eclipse framework", if it cannot be compiled or cannot
%   be run without the help or presence of some part of the Eclipse
%   framework. All java classes in packages containing the "pdt" package
%   fragment in their name fall into this category.
%   
% ad 2: "Third-party code" means any code that was originaly written as
%   part of a project other than the PDT. Files that contain or are based on
%   such code contain a notice telling you so, and telling you the
%   particular conditions under which they may be used, modified and/or
%   distributed.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

:- module(pdt_handle,[
	pdt_property/3,
	pdt_lookup/3,
	pdt_virtual_handle/3,
	pdt_property/4,	
	pdt_properties/2,
	pdt_property_cached/3,
	pdt_add_property_factory/2,
	pdt_remove_property_factory/2
]).
:-dynamic factory/2.

pdt_virtual_handle(Type,Props,virtual_handle(Props,handle(_Id,Type,_Cache))).

pdt_add_property_factory(Type,Factory):-
    factory(Type,Factory),!.
pdt_add_property_factory(Type,Factory):-
    assert(factory(Type,Factory)).

pdt_remove_property_factory(Type,Factory):-
	retractall(factory(Type,Factory)).

pdt_property(virtual_handle(_,handle(Id,Type,Cache)),Name,Value):-    
	nonvar(Id),
	!,
	pdt_property(handle(Id,Type,Cache),Name,Value).
pdt_property(virtual_handle(Props,Handle),Name,Value):-    	
	handle(_,Type,_)=Handle,
	pdt_lookup(Props,Type,Handle),
	pdt_property(Handle,Name,Value).
pdt_property(handle(Id,Type,Cache),Name,Value):-    
    var(Cache),
    !,
    pdt_lookup(handle(Id,Type,Cache)),
    pdt_property(handle(Id,Type,Cache),Name,Value).
pdt_property(handle(_,_,Cache),Name,Value):-    
    pdt_property_cached(handle(_,_,Cache),Name,Value).
pdt_property(handle(Id,Type,Cache),Name,Value):-
    factory(Type,Factory),
    Factory:get_property(handle(Id,Type,Cache),Name,Value).

pdt_property_cached(handle(_,_,Cache),Name,Value):-
    member(Prop,Cache),
    property_name_value(Prop,Name,Value).

pdt_lookup(Props,Type,H):-
    factory(Type,Factory),
    Factory:lookup_handle(Props,H),
    handle(Id,_,Cache)=H,
    nonvar(Id),
    nonvar(Cache).


property_name_value(Name,Name,true):-
    atom(Name),
    !.
property_name_value(Prop,Name,Value):-
    functor(Prop,Name,1),
    !,
    Prop=..[Name,Value].
property_name_value(Prop,Name,Value):-
	Prop=..[Name,Args],
	Value=..[array,Args].    
	
pdt_properties(_,[]).
pdt_properties(H,[Prop|Props]):-
    Prop=..[Name,Value],
    pdt_property(H,Name,Value,false),
    pdt_properties(H,Props).

pdt_property(H,Name,Value,_):-
	pdt_property(H,Name,Value),
	!.
pdt_property(_,_,Default,Default).	